package com.timepies.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.List;

import com.timepies.domain.Timepie;
import com.timepies.util.Easter.YearOutOfRangeException;

public enum Festivita {

	// GIORNI FESTIVI
	// Agli effetti della legge n° 260 del 27 maggio 1949 e della legge n° 54
	// del
	// 5 marzo 1977, sono considerati giorni festivi:
	// 1. La Domenica
	// 2. Capodanno 1° Gennaio
	// 3. Epifania 6 Gennaio
	// 4. Pasqua Mobile #
	// 5. Lunedì dell'Angelo Lunedì dopo Pasqua
	// 6. Anniversario della liberazione 25 Aprile
	// 7. Festa del lavoro 1 Maggio
	// 8. Assunzione 15 Agosto
	// 9. Ognissanti 1 Novembre
	// 10. Immacolata Concezione 8 Dicembre
	// 11. Santo Natale 25 Dicembre
	// 12. Santo Stefano 26 Dicembre
	// 13. Santo Patrono

	//@formatter:off
  CAPODANNO("Capodanno", 1, 1),
  EPIFANIA ("Epifania", 6, 1 ),
  LIBERAZIONE ("Anniversario della liberazione",25, 4 ),
  LAVORO("Festa del lavoro", 1, 5 ),
  ASSUNZIONE("Assunzione", 15, 8 ),
  OGNISSANTI("Ognissanti", 1, 11 ),
  IMMACOLATA("Immacolata Concezione", 8, 12 ),
  NATALE("Santo Natale", 25, 12 ),
  STEFANO("Santo Patrono", 26, 12 );
  //@formatter:on

	private String descrizione;
	private int giorno;
	private int mese;

	Festivita(String descrizione, int giorno, int mese) {
		this.descrizione = descrizione;
		this.giorno = giorno;
		this.mese = mese;
	}

	public String getDescrizione() {
		return descrizione;
	}

	public int getGiorno() {
		return giorno;
	}

	public int getMese() {
		return mese;
	}

	public static List<Timepie> calcolaProssimeFeste()
			throws YearOutOfRangeException {
		Calendar c = new GregorianCalendar();
		int year = c.get(Calendar.YEAR);
		List<Timepie> list = getFeste(year);
		List<Timepie> nextList = getFeste(year + 1);
		list.addAll(nextList);
		return sort(list);

	}

	public static List<Timepie> calcolaProssimiPonti()
			throws YearOutOfRangeException {
		Calendar c = new GregorianCalendar();
		int year = c.get(Calendar.YEAR);
		List<Timepie> list = getPonti(year);
		List<Timepie> nextList = getPonti(year + 1);
		list.addAll(nextList);
		return sort(list);
	}

	public static String countFesteAndPonti() throws YearOutOfRangeException {
		Calendar c = new GregorianCalendar();
		int year = c.get(Calendar.YEAR);
		List<Timepie> list = getFeste(year);
		int lavorativi = list.size();
		int ponti = 0;
		for (Timepie festa : list) {
			Calendar x = new GregorianCalendar();
			x.setTime(festa.getRowDate());
			switch (x.get(Calendar.DAY_OF_WEEK)) {

			case Calendar.WEDNESDAY:
				ponti = ponti + 2;
				break;
			case Calendar.THURSDAY:
			case Calendar.TUESDAY:
				ponti++;
				break;
			case Calendar.SUNDAY:
			case Calendar.SATURDAY:
				lavorativi--;
				break;
			}
		}

		return year + "," + list.size() + "," + lavorativi + "," + ponti;
	}

	public static List<Timepie> getFeste(int year)
			throws YearOutOfRangeException {
		List<Timepie> feste = new ArrayList<Timepie>();

		for (Festivita festa : Festivita.values())
			feste.add(new Timepie(festa, year));

		feste.add(new Timepie(Easter.find(year), "Pasqua"));
		feste.add(new Timepie(Easter.findDayAfter(year), "Pasquetta"));

		return feste;
	}

	public static List<Timepie> getPonti(int year)
			throws YearOutOfRangeException {
		List<Timepie> ponti = new ArrayList<Timepie>();
		List<Timepie> feste = getFeste(year);

		for (Timepie festa : feste) {
			Calendar c = new GregorianCalendar();
			c.setTime(festa.getRowDate());
			String txt = festa.getOggetto();
			String frase = null;

			switch (c.get(Calendar.DAY_OF_WEEK)) {
			case Calendar.MONDAY:
				frase = "Settimana corta per " + txt + " dal " + add(c, 1)
						+ " al " + add(c, 3);
				festa.setOggetto(frase);
				ponti.add(festa);
				break;
			case Calendar.TUESDAY:
				frase = "Ponte per " + txt + " dal " + add(c, -1) + " al "
						+ add(c, +1);
				festa.setOggetto(frase);
				ponti.add(festa);
				break;
			case Calendar.WEDNESDAY:
				frase = "Ponte lungo per " + txt + " dal " + add(c, -2)
						+ " al " + add(c, 2) + " oppure dal " + add(c, 0)
						+ " al " + add(c, 2);
				festa.setOggetto(frase);
				ponti.add(festa);
				break;
			case Calendar.THURSDAY:
				frase = "Ponte per " + txt + " dal " + add(c, 0) + " al "
						+ add(c, +1);
				break;
			case Calendar.FRIDAY:
				frase = "Settimana corta per " + txt + " dal " + add(c, -4)
						+ " al " + add(c, +3);
				festa.setOggetto(frase);
				ponti.add(festa);
				break;
			}
		}
		return ponti;
	}

	public static List<Timepie> sort(List<Timepie> feste) {
		Collections.sort(feste, new Comparator<Timepie>() {
			public int compare(Timepie m1, Timepie m2) {
				return m1.getRowDate().compareTo(m2.getRowDate());
			}
		});

		Calendar c = Calendar.getInstance();
		long oggi = c.getTime().getTime();
		c.add(Calendar.YEAR, 1);
		long oggiProssimoAnno = c.getTime().getTime();
		List<Timepie> festeFuture = new ArrayList<Timepie>();
		for (Timepie timepie : feste) {
			long current = timepie.getRowDate().getTime();
			if (oggi < current && current < oggiProssimoAnno)
				festeFuture.add(timepie);
		}

		return festeFuture;
	}

	public static String add(Calendar calendar, int mod) {
		calendar.add(Calendar.DAY_OF_MONTH, mod);
		return Intervallo.date.format(calendar.getTime());
	}

}

// Città Santo Patrono Data festività
// Agrigento San Gerlando 25 febbraio
// Alessandria San Baudolino e Madonna della Salve 10 novembre
// Ancona San Ciriaco di Gerusalemme 4 maggio
// Aosta San Grato 7 settembre
// Arezzo San Arezzo 7 agosto
// Ascoli Piceno Sant'Emidio 5 agosto
// Asti San Secondo primo martedì di maggio
// Avellino San Modestino 14 febbraio
// Bari San Nicola 8 maggio
// Barletta San Ruggero 30 dicembre
// Belluno San Martino di Tours 11 novembre
// Benevento San Bartolomeo 24 agosto
// Bergamo Sant'Alessandro di Bergamo 26 agosto
// Biella Santo Stefano martire 26 dicembre
// Bologna San Petronio 4 ottobre
// Bolzano Santa Maria Assunta lunedi di Pentecoste
// Brescia Santi Faustino e Giovita e Sant'Angela Merici 15 febbraio
// Brindisi San Lorenzo da Brindisi e San Teodoro d'Amasea primo fine settimana
// di settembre
// Cagliari San Saturnino 30 ottobre
// Caltanissetta San Michele Arcangelo 29 settembre
// Campobasso San Giorgio 23 aprile
// Carrara San Ceccardo 16 giugno
// Carbonia San Ponziano giovedì dopo la seconda domenica di maggio
// Caserta San Sebastiano 20 gennaio
// Catania Sant'Agata 5 febbraio
// Catanzaro San Vitaliano 16 luglio
// Cesena San Giovanni Battista 24 giugno
// Chieti San Giustino 11 Maggio
// Como Sant'Abbondio 31 agosto
// Cosenza Madonna del Pilerio 12 febbraio
// Cremona Sant'Omobono 13 novembre
// Crotone San Dionigi di Parigi 9 ottobre
// Cuneo San Michele Arcangelo 29 settembre
// Enna Maria Santissima della Visitazione 2 luglio
// Fermo Santa Maria Assunta e San Savino 16 agosto
// Ferrara San Giorgio 23 aprile
// Firenze San Giovanni Battista 24 giugno
// Foggia Madonna dei Sette Veli 22 marzo
// Forlì Madonna del Fuoco 4 febbraio
// Frosinone San Silverio e Sant'Ormisda 20 giugno
// Genova San Giovanni Battista 24 giugno
// Gorizia Santi Ilario e Taziano 16 marzo
// Grosseto San Lorenzo 10 agosto
// Iglesias Santa Chiara 11 agosto
// Imperia San Leonardo da Porto Maurizio 26 novembre
// Isernia San Celestino V 19 maggio
// La Spezia San Giuseppe 19 marzo
// L'Aquila San Massimo d'Aveia 10 giugno
// Latina Santa Maria Goretti 6 luglio
// Lecce Sant'Oronzo 26 agosto
// Lecco San Niccolò 6 dicembre
// Livorno Santa Giulia 22 maggio
// Lodi San Bassiano 19 gennaio
// Lucca San Paolino di Lucca 12 luglio
// Macerata San Giuliano 31 agosto
// Mantova Sant'Anselmo da Baggio 18 marzo
// Massa San Francesco d'Assisi 4 ottobre
// Matera Madonna della Bruna 2 luglio
// Messina Madonna della Lettera 3 giugno
// Milano Sant'Ambrogio 7 dicembre
// Modena San Geminiano 31 gennaio
// Monza San Giovanni Battista 24 giugno
// Napoli San Gennaro 19 settembre
// Novara San Gaudenzio 22 gennaio
// Nuoro Santa Maria delle Neve 5 agosto
// Olbia San Simplicio 15 maggio
// Oristano Sant'Archelao 13 febbraio
// Padova Sant'Antonio da Padova 13 giugno
// Palermo Santa Rosalia 15 luglio
// Parma Sant'Ilario 13 gennaio
// Pavia San Siro 9 dicembre
// Perugia San Costanzo 29 gennaio
// Pesaro San Terenzio 24 settembre
// Pescara San Cetteo 10 ottobre
// Piacenza Sant'Antonino 4 luglio
// Pisa San Ranieri 17 giugno
// Pistoia San Jacopo 25 luglio
// Pordenone San Marco Evangelista e Beata Vergine Maria delle Grazie 25 aprile
// e 8 settembre
// Potenza San Gerardo di Potenza 30 maggio
// Prato Santo Stefano 26 dicembre
// Ragusa San Giovanni Battista 29 agosto
// Ravenna Sant'Apollinare 23 luglio
// Reggio Calabria San Giorgio 23 aprile
// Reggio Emilia San Prospero 24 novembre
// Rieti Santa Barbara 4 dicembre
// Rimini San Gaudenzio 14 ottobre
// Roma Santi Pietro e Paolo 29 giugno
// Rovigo San Bellino 26 novembre
// Salerno San Matteo 21 settembre
// Sassari San Nicola 6 dicembre
// Savona Nostra Signora della Misericordia 18 marzo
// Siena Sant'Ansano 1 dicembre
// Siracusa Santa Lucia da Siracusa 13 dicembre
// Sondrio Santi Gervasio e Protasio 19 giugno
// Taranto San Cataldo 10 maggio
// Teramo San Berardo da Pagliara 19 dicembre
// Terni San Valentino 14 febbraio
// Torino San Giovanni Battista 24 giugno
// Trapani Sant'Alberto degli Abati 7 agosto
// Trento San Vigilio 26 giugno
// Treviso San Liberale 27 aprile
// Trieste San Giusto 3 novembre
// Udine Santi Ermacora e Fortunato 12 luglio
// Varese San Vittore il Moro 8 maggio
// Venezia San Marco Evangelista 21 novembre
// Verbania San Vittore 8 maggio
// Vercelli Sant'Eusebio 1 agosto
// Verona San Zeno 21 maggio
// Vibo Valentia San Leoluca 1 marzo
// Vicenza Madonna di Monte Berico 8 settembre
// Viterbo Santa Rosa 4 settembre
